home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
plan
/
src
/
sublist.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
230 lines
/*
* sublist management: a sublist is an array of pointer pointing to
* specific entries in the master list (see dbase.c), for example all
* entries on the same day. These extractions are done here.
* Returns pointer to sublist, or 0 if there are no entries.
*
* create_sublist(list, w)
* destroy_sublist(w)
*
*/
#ifndef MIPS
#include <stdlib.h>
#endif
#include <ctype.h>
#include <string.h>
#include <Xm/Xm.h>
#include "cal.h"
#define CHUNK 100 /* sublist allocation unit */
extern char *mystrdup();
#if defined(SUN) && !defined(SOLARIS2)
#define regcmp re_comp
#define regex re_exec
#endif
#ifdef linux
#define regcmp regcomp
#define regex regexec
#endif
#ifndef NOREGEX
extern char *regcmp(), *regex(), *__loc1;
#endif
extern int search_mode; /* 0=case, 1=lit, 2=regex */
static append_entry();
static BOOL keymatch();
extern BOOL lookup_entry(), lookup_next_entry();
/*
* create a sublist that describes the contents of a list menu. A sublist
* is an array of pointers to schedule entries (which live in the main list).
* The sublist is put into the rows of the list menu in order, but there
* are usually more menu rows than sublist entry pointers (so we have a
* few blank rows for new input).
* This routine is called whenever a list menu is created, and whenever an
* entry changes in any way. That isn't very efficient if the main list has
* hundreds or thousands of entries, so this may change in future versions.
*/
create_sublist(list, w)
register struct list *list; /* main list with all entries*/
struct listmenu *w; /* menu we are doing this for*/
{
char *key = w->key; /* keyword to look for */
BOOL found; /* TRUE if lookup succeeded */
struct lookup lookup; /* result of entry lookup */
register struct entry *ep; /* next entry to check */
register int i; /* entry counter */
list->locked++;
destroy_sublist(w); /* zap old list */
if (w->time) { /*--- time range ---*/
time_t begin = w->time;
time_t end = w->period ? begin+w->period : begin+86400;
found = lookup_entry(&lookup, list, begin, TRUE, FALSE);
while (found && lookup.trigger >= begin
&& lookup.trigger < end) {
append_entry(&w->sublist, &list->entry[lookup.index]);
found = lookup_next_entry(&lookup);
}
} else if (w->key) { /*--- keywords ---*/
if (search_mode == 1) {
register char *k;
if (!(key = mystrdup(key))) {
list->locked--;
return;
}
for (k=key; *k; k++)
if (isupper(*k)) *k = tolower(*k);
}
#ifndef NOREGEX
if (search_mode == 2)
if (!(key = regcmp(key, 0))) {
list->locked--;
return;
}
#endif
for (ep=list->entry, i=0; i < list->nentries; i++, ep++)
if (ep->message && keymatch(key, ep->message) ||
ep->script && keymatch(key, ep->script ) ||
ep->meeting && keymatch(key, ep->meeting) ||
ep->note && keymatch(key, ep->note ))
append_entry(&w->sublist, ep);
#ifndef NOREGEX
if (search_mode == 2)
free(key);
#endif
if (search_mode == 1)
free(key);
} else if (w->oneentry) { /*--- one entry --- */
for (i=0; i < list->nentries; i++)
if (w->oneentry == &list->entry[i])
append_entry(&w->sublist, w->oneentry);
} else { /*--- all ---*/
for (i=0; i < list->nentries; i++)
append_entry(&w->sublist, &list->entry[i]);
}
list->locked--;
}
/*
* destroy the sublist of a list menu. De-allocate it, and decrement the
* entry reference counts.
*/
destroy_sublist(w)
struct listmenu *w; /* menu we are doing this for*/
{
if (w->sublist) {
free(w->sublist);
w->sublist = 0;
}
}
/*
* for generating sublist by keyword: return TRUE if the keyword is in the
* string. This routine is time-critical, it is moderately optimized. It
* assumes that search strings are short; it could stop scanning earlier.
* In case insensitive mode, <key> is expected to contain lower case only.
* In regexp mode, <key> is expected to be a compiled regular expression.
*/
static BOOL keymatch(key, string)
char *key; /* keyword to look for */
char *string; /* text to look in */
{
register char *p; /* fast string scan ptr */
register char key0 = key[0]; /* first char of key */
register char c; /* temp for case conversion */
register int i; /* scan index */
register int len = strlen(key);
switch(search_mode) {
default:
case 0:
for (p=string; *p; p++)
if (p[0] == key0 &&
!strncmp(key+1, p+1, len-1))
return(TRUE);
return(FALSE);
case 1:
for (p=string; *p; p++) {
c = p[0];
if (isupper(c)) c = tolower(c);
if (c == key0) {
for (i=1; i < len; i++) {
c = p[i];
if (isupper(c)) c = tolower(c);
if (c != key[i])
break;
}
if (i == len)
return(TRUE);
}
}
return(FALSE);
#ifndef NOREGEX
case 2: {
char dummy[1024];
return(regex(key, string,
dummy, dummy, dummy, dummy, dummy,
dummy, dummy, dummy, dummy, dummy) != 0);
}
#endif
}
}
/*----------------------------- sublist management for use by above routines */
/*
* append an entry to a sublist. There is no sorting because the main list
* is sorted and will be scanned in order when a sublist is generated from it.
* A pointer to a pointer is passed; the pointed-to pointer changes if the
* list is re-allocated (or allocated for the first time). To start a new
* list, pass a pointer to a null pointer; to get rid of a list, free() it.
* Nothing is ever removed from a sublist; it is remade every time.
*/
static append_entry(sub, entry)
struct sublist **sub; /* list to append to */
struct entry *entry; /* entry to append */
{
int num; /* # of entries in old list */
int size; /* size of allocated old list*/
struct sublist *new; /* larger list if required */
register struct entry **p, **q; /* entry copy pointers */
register int i; /* entry copy counter */
num = *sub ? (*sub)->nentries : 0;
size = *sub ? (*sub)->size : 0;
if (num+1 > size) { /* need larger list */
size += CHUNK;
if (!(new = (struct sublist *)malloc(sizeof(struct sublist) +
sizeof(struct entry *) * size)))
fatal("no memory");
if (!*sub)
new->nentries = 0; /* start new list... */
else {
new->nentries = num; /* ...or copy old */
p = (*sub)->entry;
q = new->entry;
for (i=0; i < num; i++)
*q++ = *p++;
}
new->size = size;
if (*sub) /* discard old list */
free(*sub);
*sub = new;
}
(*sub)->entry[num] = entry; /* append entry */
(*sub)->nentries++;
}